﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="ActionReflector.cs" company="Collaboris Ltd.">
//   Copyright (c) Collaboris Ltd. All rights Reserved.
// </copyright>
// <summary>
//   Defines the ActionReflector type.
// </summary>
// --------------------------------------------------------------------------------------------------------------------
namespace Collaboris.Saf.Utilities
{
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Collections.Specialized;
    using System.IO;
    using System.Reflection;

    
    using Engine;

    using SharePoint.Wss.Attributes;
    using SharePoint.Wss.Entities;

    using Utils;

    using Definitions;

    using Spring.Collections;
    using Spring.Context.Support;
    using Spring.Core.IO;
    using Spring.Core.TypeResolution;
    using Spring.Objects.Factory;
    using Spring.Objects.Factory.Config;
    using Spring.Objects.Factory.Xml;

    /// <summary>
    /// Helper class for the Action reflector.    
    /// </summary>
    [Serializable]
    public class ActionReflector
    {

        /// <summary>
        /// Gets the full Action Graph by using Reflection and 
        /// Spring aliases files etc..
        /// </summary>
        /// <returns></returns>
        public static SafClassDefinitionCollection GetActionDefinitionGraph()
        {
            SafClassDefinitionCollection allSafClassDefinitions = new SafClassDefinitionCollection();
            IDictionary<string, string> allActions = GetActions();

            // Loop through all the Actions ...
            foreach (KeyValuePair<string, string> action in allActions)
            {
                // get the current Action Type...
                Type actionType = Type.GetType(action.Value);

                // Process the Action "Class" Level Definition ...
                SafClassDefinition definition = ProcessClassDefinition(actionType, null);
                if (definition != null)
                    allSafClassDefinitions.Add(Convert4PartTypeNameToKey(actionType.AssemblyQualifiedName), definition);
            }

            return allSafClassDefinitions;
        }

        /// <summary>
        /// Determines whether the specified type is action.
        /// </summary>
        /// <param name="type">The type.</param>
        /// <returns>
        /// 	<c>true</c> if the specified type is action; otherwise, <c>false</c>.
        /// </returns>
        private static bool IsAction(Type type)    
        {            
            if (type == null) 
            {        
                throw new ArgumentNullException("type");    
            }   
            
            foreach (Type @interface in type.GetInterfaces()) 
            {        
               if (@interface.Equals(typeof(IAction))) 
                {                        
                    // if needed, you can also return the type used as generic argument                        
                    return true;                
                }   
            }    
            
            return false;
        }

        /// <summary>
        /// Processes the class definition.
        /// </summary>
        /// <param name="classType">Type of the class.</param>
        /// <returns></returns>
        private static SafClassDefinition ProcessClassDefinition(Type classType, SafPropertyDefinition parentPropertDefinition)
        {
            // Get the Class Attribute, if one ? ...
            CollaborisClassAttribute classAttribute = GetClassAttribute(classType);
            if (classAttribute != null)
            {
                if (!classAttribute.DisableDocumentation)
                {
                    SafClassDefinition definition = new SafClassDefinition();
                    definition.Parent = parentPropertDefinition;
                    //definition.Full4PartName = actionName;
                    definition.FullName = classType.FullName;
                    definition.ClassName = classType.Name;
                    definition.Title = classAttribute.Title;
                    definition.ReleaseStatus = classAttribute.ReleaseStatus;
                    definition.Summary = classAttribute.Summary;
                    definition.Remarks = classAttribute.Remarks;
                    definition.ClassGuid = classAttribute.ClassGuid;
                    definition.UndoImplemented = classAttribute.UndoImplemented;
                    definition.ContactAuthorEmail = classAttribute.ContactAuthorEmail;
                    definition.Alias = GetAlias(classType);
                    definition.UnderlyingType = classType;
                    definition.SupportFiles = classAttribute.SupportFiles;
                    definition.NameSpace = classType.Namespace;
                    definition.AssemblyName = classType.Assembly.GetName().Name;
                    definition.AssemblyFullName = classType.Assembly.FullName;
                    definition.AssemblyCodebaseLocation = classType.Assembly.CodeBase;
                    //Type genericType = GetSoleEntityType(classType);
                    //if (genericType != null)
                    //    definition.GenericTypeName = genericType.FullName;

                    if (classType.IsGenericType)
                    {
                        definition.IsGeneric = true;
                    }

                    if (IsAction(classType))
                        definition.IsAction = true;


                    // loop around all the properties and look for a CollaborisPropertyAttribute
                    ProcessPropertyDefinitions(classType, definition.Properties, definition);

                    return definition;
                }
            }

            return null;
        }

        /// <summary>
        /// Sets the property defintions.
        /// </summary>
        /// <param name="actionType">Type of the action.</param>
        /// <param name="collection">The collection.</param>
        public static void ProcessPropertyDefinitions(Type actionType, SafPropertyDefinitionCollection collection, SafClassDefinition parentDefinition)
        {
            PropertyInfo[] propertyInfos = actionType.GetProperties();
            foreach (PropertyInfo propInfo in propertyInfos)
            {
                CollaborisPropertyAttribute attribute = GetSafAttribute(propInfo);
                if (attribute != null)
                {
                    SafPropertyDefinition propertyDefinition = new SafPropertyDefinition();
                    propertyDefinition.Title = attribute.Title;
                    propertyDefinition.Summary = attribute.Summary;
                    propertyDefinition.ReadMore = attribute.ReadMore;
                    propertyDefinition.Example = attribute.Example;
                    propertyDefinition.Remarks = attribute.Remarks;
                    propertyDefinition.SerializedExample = attribute.SerializedExample;
                    propertyDefinition.OutputProperty = attribute.OutputProperty;
                    propertyDefinition.Name = propInfo.Name;
                    propertyDefinition.UnderlyingType = propInfo.PropertyType;
                    propertyDefinition.RenderAsExpression = attribute.RenderAsExpression;
                    propertyDefinition.Required = attribute.Required;
                    propertyDefinition.ParentClassDefinition = parentDefinition;
                    collection.Add(propInfo.Name, propertyDefinition);

                    // do we recurse here ? - this is for an entity in an entity.
                    if (propInfo.PropertyType.IsClass &&
                        !propInfo.PropertyType.IsValueType &&
                        !propInfo.PropertyType.IsPrimitive &&
                        propInfo.PropertyType.FullName != "System.String")
                    {
                        Type subType;
                        if (propInfo.Name == "EntityList")
                        {
                            subType = GetSoleEntityType(actionType);
                            
                        }
                        else
                            subType = propInfo.PropertyType;

                        if (subType.IsGenericType)
                        {
                            propertyDefinition.GenericTypeFullName = GetGenericTypeName(subType, true, true);
                            Type parentGenericType = GetGenericTypeFromGenericWithArgs(subType);
                            if (parentGenericType != null)
                            {
                                propertyDefinition.GenericTypeClassDefinition = ProcessClassDefinition(parentGenericType, propertyDefinition);
                                propertyDefinition.GenericUnderlyingType = GetGenericTypeFromGenericWithArgs(parentGenericType);

                                
                            }

                            // now if the property has generic ars such as List<string, someentity> lets 
                            // go and create a Class Definition for those args that actually
                            // Saf Classes (i.e. contain the CollaborisClassAttribute.
                            Dictionary<string, SafClassDefinition> args = new Dictionary<string, SafClassDefinition>();
                            foreach (Type genericArgument in subType.GetGenericArguments())
                            {
                                args.Add(genericArgument.FullName, ProcessClassDefinition(genericArgument, propertyDefinition));
                                propertyDefinition.GenericTypeArguments = args;
                            }
                        }

                        SafClassDefinition classDefinition = ProcessClassDefinition(subType, propertyDefinition);
                        propertyDefinition.ClassDefinition = classDefinition;
                    }
                }
            }
        }



        /// <summary>
        /// Fixes up a Generic Type name so that it displays properly for output.
        /// Fixes output from
        /// wwBusiness`1 to wwBusiness<EntityType>
        /// </summary>
        /// <param name="loType"></param>
        /// <param name="ReturnFullTypeName"></param>
        /// <returns></returns>
        public static string GetGenericTypeName(Type GenericType, bool ReturnFullTypeName, bool ExcludesArgs)
        {
            // *** Make sure the type is indeed generic in which case the` is in the name
            int Index = GenericType.Name.IndexOf("`");
            if (Index == -1)
            {
                if (!ReturnFullTypeName)
                    return GenericType.Name;


                return GenericType.Namespace + "." + GenericType.Name;
            }


            // *** Strip off the Genric postfix
            string TypeName = GenericType.Name.Substring(0, Index);
            string FormattedName = TypeName;


            // *** Parse the generic type arguments
            Type[] GenericArguments = GenericType.GetGenericArguments();
            string GenericOutput = "<";
            bool Start = true;
            foreach (Type GenericArg in GenericArguments)
            {
                if (Start)
                {
                    GenericOutput += GenericArg.Name;
                    Start = false;
                }
                else
                    GenericOutput += "," + GenericArg.Name;
            }


            GenericOutput += ">";

            if (!ExcludesArgs)
                FormattedName += GenericOutput;


            if (!ReturnFullTypeName)
                return FormattedName;


            // *** Add the full namespace
            return GenericType.Namespace + "." + FormattedName;
        }

        public static Type GetGenericTypeFromGenericWithArgs(Type GenericType)
        {
            // *** Make sure the type is indeed generic in which case the` is in the name
            int index = GenericType.Name.IndexOf("`");
            
            // *** Strip off the Genric postfix
            string typeName = GenericType.Name.Substring(0, index);

            int numOfArgs = GenericType.GetGenericArguments().Length;
            if (numOfArgs >0)
            {
                typeName += "`" + numOfArgs;
            }

            string formattedName = GenericType.Namespace + "." + typeName;

            formattedName += "," + GenericType.Assembly.FullName;

            return Type.GetType(formattedName);

        }




        /// <summary>
        /// Converts the 4 part type name to a key.
        /// </summary>
        /// <param name="value">The value.</param>
        /// <returns></returns>
        public static string Convert4PartTypeNameToKey(string value)
        {
            return value.Replace(" ", "").ToLowerInvariant();
        }

        /// <summary>
        /// Convert4s the part type name to key.
        /// </summary>
        /// <param name="actionType">Type of the action.</param>
        /// <returns></returns>
        public static string Convert4PartTypeNameToKey(Type actionType)
        {
            string fourPartName = actionType.AssemblyQualifiedName;
            return ActionReflector.Convert4PartTypeNameToKey(fourPartName);
        }

        /// <summary>
        /// Gets the Saf Property attribute, based on a string type ref.
        /// </summary>
        /// <param name="fourPartTypeName">Name of the four part type.</param>
        /// <returns></returns>
        public static CollaborisPropertyAttribute GetSafPropertyAttribute(string fourPartTypeName, string propertyName)
        {
            Type objType = Type.GetType(fourPartTypeName);
            if (objType != null)
            {
                return GetSafPropertyAttribute(objType, propertyName);
            }

            return null;
        }

        /// <summary>
        /// Gets the saf property attribute.
        /// </summary>
        /// <param name="objType">Type of the obj.</param>
        /// <param name="propertyName">Name of the property.</param>
        /// <returns></returns>
        public static CollaborisPropertyAttribute GetSafPropertyAttribute(Type objType, string propertyName)
        {
            if (objType != null)
            {
                PropertyInfo[] propertyInfos = objType.GetProperties();
                foreach (PropertyInfo propInfo in propertyInfos)
                {
                    // match on the property Name ? ...
                    if (propInfo.Name.ToLower() == propertyName.ToLower())
                    {
                        Attribute[] allAttribs = System.Attribute.GetCustomAttributes(propInfo);
                        foreach (Attribute typeAttribute in allAttribs)
                        {
                            if (typeAttribute is CollaborisPropertyAttribute)
                            {
                                return typeAttribute as CollaborisPropertyAttribute;
                            }
                        }
                    }
                }
            }

            return null;
        }

        /// <summary>
        /// Gets the action class attribute, based on a string type ref.
        /// </summary>
        /// <param name="fourPartTypeName">Name of the four part type.</param>
        /// <returns></returns>
        public static CollaborisClassAttribute GetClassAttribute(string fourPartTypeName)
        {
            Type actionType = Type.GetType(fourPartTypeName);
            if (actionType != null)
            {
                return GetClassAttribute(actionType);
            }

            return null;
        }

        /// <summary>
        /// Gets a Saf Action class attribute.
        /// </summary>
        /// <param name="action">The action.</param>
        /// <returns></returns>
        public static CollaborisClassAttribute GetClassAttribute(Type action)
        {
            if (action != null)
            {
                Attribute[] allAttribs = System.Attribute.GetCustomAttributes(action);
                foreach (Attribute typeAttribute in allAttribs)
                {
                    if (typeAttribute is CollaborisClassAttribute)
                    {
                        return typeAttribute as CollaborisClassAttribute;
                    }
                }
            }

            return null;
        }

        /// <summary>
        /// Gets the Aliases Action name from the action type.
        /// </summary>
        /// <returns></returns>
        public static IDictionary<string,string> GetActions()
        {
            IDictionary<string, string> actionsAssemblies = GetActionAssemblies();
            IDictionary<string, string> aliasesActions = new Dictionary<string, string>();

            foreach (KeyValuePair<string, string> de in actionsAssemblies)
            {
                IDictionary<string, string> actions = GetActions(de.Value);
                foreach (KeyValuePair<string, string> action in actions)
                {
                    aliasesActions.Add(action);
                }
            }           
                        
            // aliasesActions.Add("Action.SetWelcomePage", "Collaboris.Saf.Actions.MOSS.Publishing.SetWelcomePage, Collaboris.Saf.Actions.MOSS, Version=2.0.0.0, Culture=neutral, PublicKeyToken=182db3eac6a9e195");
            return aliasesActions;
        }

        /// <summary>
        /// Gets the list of actions available for the given assembly.
        /// </summary>
        /// <param name="assemblyName"></param>
        /// <returns></returns>
        public static IDictionary<string, string> GetActions(string assemblyName)
        {
            Assembly actionAssembly  = Assembly.Load(assemblyName);
            Type[] types = actionAssembly.GetTypes();
            IDictionary<string, string> actionTypes = new Dictionary<string, string>();
            foreach (Type type in types)
            {
                Type[] interfaces = type.GetInterfaces();
                foreach (Type interfaceType in interfaces)
                {
                    if (interfaceType.Equals(typeof(IAction)))
                    {
                        // Key = Aliases...
                        // value = Full4PartName...
                        actionTypes.Add(GetAlias(type), type.FullName + "," + assemblyName);
                        break;
                    }
                }
            }

            return actionTypes;
        }

        /// <summary>
        /// Gets the list of ActionAssemblies from the Manifest.
        /// </summary>
        /// <returns></returns>
        public static IDictionary<string, string> GetActionAssemblies()
        {
            SAFManifest safManifest;

            /// Get it from the Spring.net aliases.xml 
            /// TODO
            using (Stream stream = File.OpenRead(Globals.ManifestFilePath))
            {
                InputStreamResource resource = new InputStreamResource(stream, "SAFManifest");

                XmlObjectFactory xmlObjectFactory = new XmlObjectFactory(resource);

                safManifest = (SAFManifest)xmlObjectFactory.GetObject(Globals.ManifestName);

                return safManifest.ActionsAssemblies;
            }
        }

        /// <summary>
        /// Gets the Entity type for the supplied action type.
        /// </summary>
        /// <param name="actionType"></param>
        /// <returns></returns>
        public static Type[] GetEntityType(Type actionType)
        {
            // Note: This should return only one Entity type. 
            Type baseActionType = actionType.BaseType;
            return baseActionType.GetGenericArguments();
        }

        /// <summary>
        /// Gets the Generic Type set on the Action.
        /// </summary>
        /// <param name="fourPartTypeName">Name of the four part type.</param>
        /// <returns></returns>
        public static Type GetSoleEntityType(string fourPartTypeName)
        {
            Type actionType = Type.GetType(fourPartTypeName);
            return GetSoleEntityType(actionType);

        }


        /// <summary>
        /// Gets the Generic Type set on the Action.
        /// </summary>
        /// <param name="actionType"></param>
        /// <returns></returns>
        public static Type GetSoleEntityType(Type actionType)
        {
            Type[] types = GetEntityType(actionType) ;
            if (types == null)
                return null;
            if (types.Length == 0)
                return null;

            return types[0];
        }


        /// <summary>
        /// Gets a Saf Action class attribute.
        /// </summary>
        /// <param name="action">The action.</param>
        /// <returns></returns>
        public static CollaborisPropertyAttribute GetSafAttribute(PropertyInfo obj)
        {
            if (obj != null)
            {
                Attribute[] allAttribs = System.Attribute.GetCustomAttributes(obj);
                foreach (Attribute typeAttribute in allAttribs)
                {
                    if (typeAttribute is CollaborisPropertyAttribute)
                    {
                        return typeAttribute as CollaborisPropertyAttribute;
                    }
                }
            }

            return null;
        }

        /// <summary>
        /// Gets the action properties.
        /// </summary>
        /// <param name="obj">The obj.</param>
        /// <returns></returns>
        //public static IDictionary<string, string> GetActionProperties(object obj)
        //{
        //    if (obj == null)
        //        return null;

        //    PropertyInfo[] allProperties = obj.GetType().GetProperties();

        //    Dictionary<string, string> dictionary = new Dictionary<string, string>();
        //    foreach (PropertyInfo info in allProperties)
        //    {
        //        // if (info.Name. == "")
        //        dictionary.Add(info.Name, info.GetValue(obj, null).ToString());
        //    }

        //    return dictionary;
        //}

        /// <summary>
        /// Responsible for Processing the Input and Output Properties
        /// on both the Entity and Action.
        /// </summary>
        /// <param name="action">The action.</param>
        /// <param name="context">The context.</param>
        public static void ProcessProperties(IAction action, SafContext context)
        {
            /*
            PropertyPlaceholderConfigurer configurer = new PropertyPlaceholderConfigurer();
            NameValueCollection nvc = context.ActionProperties.ToNameValueCollection();
            configurer.IgnoreUnresolvablePlaceholders = true;
            configurer.PlaceholderPrefix = Globals.DynamicPropertyPrefix;
            configurer.PlaceholderSuffix = Globals.DynamicPropertySuffix;

            if (action.EntityList != null)
            {
                for (int i = 0; i < action.EntityList.Length; i++)
                {
                    EntityBase entity = action.EntityList[i];

                    PropertyInfo[] allProperties = entity.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);
                    
                    foreach (PropertyInfo info in allProperties)
                    {
                        CollaborisPropertyAttribute attribute = TryGetSafPropertyAttribute(info);
                        if (attribute is InputAttribute)
                        {
                            ResolveInputProperty(info, entity, configurer, nvc);
                        }

                        if (attribute is OutputAttribute)
                        {
                            ResolveOutputProperty(info, entity, context, action);
                        }
                    }
                }
            }
             */
        }

        /// <summary>
        /// Resolves the any output properties on the Entity.
        /// </summary>
        /// <param name="prop">The prop.</param>
        /// <param name="obj">The obj.</param>
        /// <param name="context">The context.</param>
        /// <param name="action">The action.</param>
        private static void ResolveOutputProperty(PropertyInfo prop, EntityBase entity, SafContext context, IAction action)
        {
            Type propertyType = prop.PropertyType;

            if (prop.CanRead)
            {
                object outputtedValue = prop.GetValue(entity, null);
                if (outputtedValue != null)
                {
                    // Write the value back to context....
                    SetOutputPropertyValueOnTheContext(prop, entity, context, outputtedValue.ToString(), action);
                }

                // do we recurse here ? - this is for an entity in an entity.
                if (prop.PropertyType.IsClass &&
                    !prop.PropertyType.IsValueType &&
                    !prop.PropertyType.IsPrimitive &&
                    prop.PropertyType.FullName != "System.String")
                {
                    foreach (PropertyInfo info in propertyType.GetProperties(BindingFlags.Public | BindingFlags.Instance))
                    {
                        ResolveOutputProperty(info, entity, context, action);
                    }
                }
            }
        }

        /// <summary>
        /// Sets an <see cref="OutputAttribute"/> property value, into the Context,
        /// with the Placeholder string that the user set. If the Action doesn't set the
        /// PlaceHolder then its just ignored.
        /// To get the PlaceHolder, this method makes a call into the original Object Definition,
        /// so that it can be read. This is the only way to do this as Placeholder will have attempted to
        /// be resolved (by Spring) and will not be available as a value on the current object.
        /// </summary>
        /// <param name="info">The info.</param>
        /// <param name="o">The o.</param>
        /// <param name="context">The context.</param>
        /// <param name="value">The value.</param>
        /// <param name="action">The action.</param>
        private static void SetOutputPropertyValueOnTheContext(PropertyInfo info, object o, SafContext context, string value, IAction action)
        {
            if (!string.IsNullOrEmpty(value))
            {
                string placeHolderName = GetPlaceHolderNameForOutputProperty(action, o as EntityBase);
                
                if (!string.IsNullOrEmpty(placeHolderName))
                {                   
                  context.ActionProperties.Add(placeHolderName, value, true);                  
                }               
            }
        }

        private static string GetPlaceHolderNameForOutputProperty(IAction action, EntityBase entity)
        {
            //XmlApplicationContext springContext = action.Macro.SpringContext;
            //IDictionary aliasesObjectNames = ObjectFactoryUtils.ObjectsOfTypeIncludingAncestors(
            //                                        springContext.ObjectFactory,
            //                                        typeof(Collaboris.Saf.Engine.EntityBase),
            //                                        true,
            //                                        true);

            //bool r = springContext.ObjectFactory.ContainsObject("Calulator#" + entity.GetHashCode().ToString());

            //RootObjectDefinition rod = springContext.GetObjectDefinition("MacroToProcess", false) as RootObjectDefinition;
            
            return string.Empty;
        }
        
        /// <summary>
        /// Resolves a property that has been created at run time.
        /// </summary>
        /// <param name="prop">The prop.</param>
        /// <param name="obj">The obj.</param>
        /// <param name="configurer">The configurer.</param>
        /// <param name="properties">The properties.</param>
        private static void ResolveInputProperty(
                                            PropertyInfo prop,
                                            object obj,
                                            PropertyPlaceholderConfigurer configurer,
                                            NameValueCollection properties)
        {
            Type propertyType = prop.PropertyType;

            if (prop.CanRead && prop.CanWrite)
            {
                string oldValue = prop.GetValue(obj, null) as string;
                if (!string.IsNullOrEmpty(oldValue))
                {
                    string newValue = configurer.ParseString(properties, oldValue, new HashedSet());
                    if (oldValue != newValue)
                    {
                        prop.SetValue(obj, newValue, null);
                    }
                }

                // do we recurse here ? - this is for an entity in an entity.
                if (prop.PropertyType.IsClass && 
                    ! prop.PropertyType.IsValueType && 
                    ! prop.PropertyType.IsPrimitive && 
                    prop.PropertyType.FullName != "System.String")
                {
                    foreach (PropertyInfo info in propertyType.GetProperties(BindingFlags.Public | BindingFlags.Instance))
                    {
                        ResolveInputProperty(info, obj, configurer, properties);
                    }
                }
            }
        }

        /// <summary>
        /// Determines whether the Property has the correct 
        /// <see cref="CollaborisPropertyAttribute"/> applied to it.
        /// </summary>
        /// <param name="property">The property.</param>
        /// <returns>
        /// 	<c>true</c> if it has the attribut returns true; otherwise, <c>false</c>.
        /// </returns>
        private static CollaborisPropertyAttribute TryGetSafPropertyAttribute(PropertyInfo property)
        {
            if (property == null)
                return null;

            CollaborisPropertyAttribute attribute =
                    Attribute.GetCustomAttribute(property, typeof(CollaborisPropertyAttribute)) as CollaborisPropertyAttribute;
            
            return attribute;
        }

        /// <summary>
        /// Gets the alias.
        /// </summary>
        /// <param name="assemblyQualifiedName">4 Part Assemmbly Qualified Name.</param>
        /// <returns></returns>
        public static string GetAlias(string assemblyQualifiedName)
        {
            Type type = Type.GetType(assemblyQualifiedName);
            return GetAlias(type);
        }

        /// <summary>
        /// Gets the aliases.
        /// </summary>
        /// <param name="objectType">Type of the object.</param>
        /// <returns></returns>
        public static string GetAlias(Type objectType)
        {
            string aliases = objectType.FullName;
            List<string> aliasesFiles = GetAliasesFromDir();
            XmlApplicationContext context = new XmlApplicationContext(aliasesFiles.ToArray());

            // Get the aliases objects...
            IDictionary aliasesObjectNames = ObjectFactoryUtils.ObjectsOfTypeIncludingAncestors(
                                                    context.ObjectFactory,
                                                    typeof(Collaboris.Saf.SpringExtensions.Objects.Factory.Config.TypeAliasConfigurer),
                                                    true, 
                                                    true);

            foreach (object aliasTypeObjects in aliasesObjectNames.Values)
            {
                if (aliasTypeObjects != null)
                {
                    SpringExtensions.Objects.Factory.Config.TypeAliasConfigurer typeAliasConfigurer 
                        = aliasTypeObjects as SpringExtensions.Objects.Factory.Config.TypeAliasConfigurer;

                    if (typeAliasConfigurer != null)
                    {
                        IDictionary typeAliases = typeAliasConfigurer.TypeAliases;
                        foreach (DictionaryEntry entry in typeAliasConfigurer.TypeAliases)
                        {
                            // The new version of Spring doesn't have a 'GenericTypeResolver' any more,
                            // so hoping this does the job.
                            GenericTypeResolver resolver = new GenericTypeResolver();
                            Type aliasType = resolver.Resolve(entry.Value.ToString());
                            if (objectType.Equals(aliasType))
                            {
                                return entry.Key.ToString();
                            }
                        }
                    }
                }
            }

            return aliases;
        }

        /// <summary>
        /// Gets the object type from the aliases / type fullname string .
        /// </summary>
        /// <returns>Aliases Type</returns>
        public static Type GetTypeFromAliases(string aliases)
        {
            List<string> aliasesFiles = GetAliasesFromDir();
            XmlApplicationContext context = new XmlApplicationContext(aliasesFiles.ToArray());

            // Get the aliases objects...
            IDictionary aliasesObjectNames = ObjectFactoryUtils.ObjectsOfTypeIncludingAncestors(
                                                    context.ObjectFactory,
                                                    typeof(Collaboris.Saf.SpringExtensions.Objects.Factory.Config.TypeAliasConfigurer),
                                                    true,
                                                    true);

            foreach (object aliasTypeObjects in aliasesObjectNames.Values)
            {
                if (aliasTypeObjects != null)
                {
                    SpringExtensions.Objects.Factory.Config.TypeAliasConfigurer typeAliasConfigurer
                        = aliasTypeObjects as SpringExtensions.Objects.Factory.Config.TypeAliasConfigurer;

                    if (typeAliasConfigurer != null)
                    {
                        IDictionary typeAliases = typeAliasConfigurer.TypeAliases;
                        foreach (DictionaryEntry entry in typeAliasConfigurer.TypeAliases)
                        {
                            if (entry.Key.ToString().Equals(aliases,StringComparison.OrdinalIgnoreCase))
                            {
                                GenericTypeResolver resolver = new GenericTypeResolver();
                                Type aliasType = resolver.Resolve(entry.Value.ToString());
                                return aliasType;
                            }
                        }
                    }
                }
            }
            return null;
        }

        public static bool IsNull(object o)
        {
            return (o == null) ? true : false;
        }

        public static object GetValue(PropertyInfo propertyInfo, object obj)
        {
            object returnValue = null;
            if (propertyInfo != null)
            {
                if (obj == null)
                {
                    return null;
                }
                try
                {
                    object tempObj = propertyInfo.GetValue(obj, null);
                    if (tempObj != null)
                    {
                        returnValue = tempObj;
                    }
                }
                catch (Exception)
                {
                    return null;
                }
            }

            return returnValue;
        }

        /// <summary>
        /// Gets the aliases from dir.
        /// </summary>
        /// <returns></returns>
        public static List<string> GetAliasesFromDir()
        {
            List<string> list = new List<string>();
            string aliasResource = "file://" + Globals.AliasesFilePath;
            string[] files = Directory.GetFiles(Globals.CollaborisConfigPath, Globals.AliasDirectorySearchPattern);

            list.AddRange(files);
            if (files.Length > 0)
            {
                foreach (string file in files)
                {
                    list.Add("file://" + file);
                }
            }

            // now add the standard collaboris alias in.
            list.Add(aliasResource);
            return list;
        }
        
        #region Spring Xml Helper Methods

      
        #endregion

    }
}

